package cqrtplm.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.basic.entity.BaseObject;
import com.hustcad.plm.basic.util.TyplmEntityBaseUtil;
import com.hustcad.plm.pdm.common.model.dto.search.SearchAttributeDTO;
import com.hustcad.plm.pdm.common.model.dto.search.SearchAttributeGroupDTO;
import com.hustcad.plm.pdm.common.model.dto.search.SearchColumnDTO;
import com.hustcad.plm.pdm.common.model.dto.search.SearchConditionDTO;
import com.hustcad.plm.pdm.common.model.dto.search.SearchTypeDTO;
import com.hustcad.plm.pdm.common.model.vo.search.ResultEntityVO;
import com.hustcad.plm.pdm.common.model.vo.search.SearchAttributeVO;
import com.hustcad.plm.pdm.common.model.vo.search.SearchConditionVO;
import com.hustcad.plm.pdm.common.model.vo.search.SearchTypeVO;
import com.hustcad.plm.pdm.common.model.vo.tableview.TableViewDescriptorVO;
import com.hustcad.plm.pdm.common.service.search.TyplmCommonSearchService;
import com.hustcad.plm.pdm.common.service.tableview.TyplmCommonTableViewService;
import com.hustcad.plm.pdm.enumeration.model.dto.TyEnumerationItemValue;
import com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationItemService;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowObject;
import com.hustcad.plm.pdm.flowbusiness.model.entity.WorkFlowObjectPackage;
import com.hustcad.plm.pdm.flowbusiness.model.vo.FlowObjectStructuredParamVO;
import com.hustcad.plm.pdm.flowbusiness.service.TyplmWorkFlowObjectPackageService;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeDefService;
import com.hustcad.plm.pdm.iteration.event.TyQueryByIdentifierEvent;
import com.hustcad.plm.pdm.partbom.service.TyplmPartService;
import com.hustcad.plm.pdm.partbom.vo.TyPartAllVO;
import com.hustcad.plm.pdm.type.service.TyplmTypeService;
import com.hustcad.plm.pdm.user.service.TyplmUserService;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlowContainerView;
import com.hustcad.plm.pdm.workflow.service.TyplmWorkFlowContainerService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.entity.part.PartDO;
import com.ty.basic.entity.type.TypeDO;
import com.ty.basic.vo.AttributeVO;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.dto.UserQueryDTO;
import cqrtplm.mapper.RTPartMapper;
import cqrtplm.service.AttributePropagationService;
import cqrtplm.service.QueryPartService;
import cqrtplm.vo.ExportEBOMPartsDataVO;
import cqrtplm.vo.ExportMaterialCodePartsDataVO;
import cqrtplm.vo.ExportPatternCodePartsDataVO;
import cqrtplm.vo.ExportStandardPartsDataVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class QueryPartServiceImpl implements QueryPartService {

    @Resource
    private TyplmCommonSearchService typlmCommonSearchService;

    @Resource
    private TyplmAttributeDefService typlmAttributeDefService;

    @Resource
    private TyplmTypeService typlmTypeService;

    @Resource
    private TyplmUserService typlmUserService;

    @Resource
    private TyplmEnumerationItemService itemService;

    @Resource
    private TyplmWorkFlowContainerService typlmWorkFlowContainerService;

    @Resource
    private TyplmWorkFlowObjectPackageService typlmWorkFlowObjectPackageService;

    @Resource
    private RTPartMapper rtPartMapper;

    @Resource
    private AttributePropagationService attributePropagationService;

    @Resource
    private TyplmPartService typlmPartService;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private TyplmCommonTableViewService typlmCommonTableViewService;


    @Override
    public PageInfo<ResultEntityVO> queryPartData(UserQueryDTO userQueryDTO, boolean needThumbnailFile) {
        return queryPartData(userQueryDTO, needThumbnailFile, false);
    }

    @Override
    public PageInfo<ResultEntityVO> queryPartData(UserQueryDTO userQueryDTO, boolean needThumbnailFile, boolean needIBA) {
        String typeInthid = userQueryDTO.getTypeInthid();
        TypeDO typeDO = typlmTypeService.getLastTypeByLogicalidentifier(typeInthid.split("\\|")[1]);
        SearchConditionVO searchCondition = new SearchConditionVO();
        List<SearchTypeVO> typeList = new ArrayList<>();
        SearchTypeVO searchTypeVO = new SearchTypeVO();
        searchTypeVO.setTypeInthid(typeInthid);
        searchTypeVO.setTypeOid(typeDO.getOid());
        typeList.add(searchTypeVO);
        searchCondition.setTypeList(typeList);
        return queryObjectByIbaValueAndType(typeDO.getOid(), typeInthid,
                                            userQueryDTO, needThumbnailFile, needIBA);
    }

    public PageInfo<ResultEntityVO> queryObjectByIbaValueAndType(BigInteger typeOid, String typeName,
                                                                 UserQueryDTO userQueryDTO, boolean needThumbnailFile, boolean needIBA) {
        SearchConditionDTO searchConditionDTO = new SearchConditionDTO();
        List<SearchTypeDTO> typeList = new ArrayList<>();
        SearchTypeDTO searchTypeDTO = new SearchTypeDTO();
        searchTypeDTO.setTypeOid(typeOid);
        searchTypeDTO.setTypeInthid(typeName);
        typeList.add(searchTypeDTO);
        searchConditionDTO.setTypeList(typeList);
        searchConditionDTO.setContextList(new ArrayList<>());
        searchConditionDTO.setConditionJoint("and");
        List<SearchTypeVO> list = new ArrayList<>();
        SearchTypeVO searchTypeVO = new SearchTypeVO();
        searchTypeVO.setTypeOid(typeOid);
        searchTypeVO.setTypeInthid(typeName);
        list.add(searchTypeVO);

        if(needIBA){
            TableViewDescriptorVO descriptorVO = new TableViewDescriptorVO();
            descriptorVO.setTableid("AdvanceSearchView");
            descriptorVO.setViewgroup("type");
            SearchConditionVO searchConditionVO = new SearchConditionVO();
            searchConditionVO.setTypeList(list);
            descriptorVO.setSearchCondition(searchConditionVO);
            List<SearchColumnDTO> searchColumnList = typlmCommonTableViewService.getSearchColumnList(descriptorVO);
            searchConditionDTO.setColumns(searchColumnList);
        }

        List<TyEnumerationItemValue> lifeCycleState = itemService.getMergedEnumItems(
                Collections.singletonList("LifeCycleState"));
        Map<String, String> lifeCycleStateMap = lifeCycleState.stream().collect(Collectors.toMap(
                TyEnumerationItemValue::getName,
                TyEnumerationItemValue::getCode,
                (existing, replacement) -> existing // 保留现有的值，或者根据需求选择其他策略
        ));


        List<SearchAttributeVO> searchAttribute = typlmCommonSearchService.getSearchAttribute(list);
        Map<String, SearchAttributeVO> attributeMap = searchAttribute.stream()
                .filter(Objects::nonNull)
                .filter(attr -> attr.getPropertyName() != null)
                .collect(Collectors.toMap(
                        attr -> attr.getPropertyName().toLowerCase(),
                        Function.identity(),
                        (existing, replacement) -> existing
                ));

        if ("1".equals(userQueryDTO.getIsQueryDTO())) {
            Map<String, UserQueryDTO.ConditionGroup> conditions1 = userQueryDTO.getConditions();
            Set<String> ibaSet = conditions1.keySet();
            List<String> ibaNameList = new ArrayList<>();
            for (String ibaName : ibaSet) {
                if (!attributeMap.containsKey(ibaName)) {
                    ibaNameList.add(ibaName);
                }
            }
            if (CollUtil.isNotEmpty(ibaNameList)) {
                List<AttributeVO> attributeVOS = typlmAttributeDefService.queryAttrDefByNameListForRedis(ibaNameList);
                for (AttributeVO attributeVO : attributeVOS) {
                    SearchAttributeVO searchAttributeVO = new SearchAttributeVO();
                    searchAttributeVO.setPropertyName(attributeVO.getAttributeDefName());
                    searchAttributeVO.setPropertyType("String");
                    searchAttributeVO.setIbaDefOid(new BigInteger(attributeVO.getOid()));
                    searchAttributeVO.setIbaDefOtype(attributeVO.getOType());
                    searchAttributeVO.setTypeList(list);
                    attributeMap.put(attributeVO.getAttributeDefName().toLowerCase(), searchAttributeVO);
                }
            }
        }


        List<SearchAttributeGroupDTO> conditionGroups = new ArrayList<>();
        if ("1".equals(userQueryDTO.getIsQueryDTO())) {
            Map<String, UserQueryDTO.ConditionGroup> conditionDTOS = userQueryDTO.getConditions();
            for (Map.Entry<String, UserQueryDTO.ConditionGroup> entry : conditionDTOS.entrySet()) {
                List<SearchAttributeDTO> conditions = new ArrayList<>();
                String key = entry.getKey().toLowerCase();
                UserQueryDTO.ConditionGroup value = entry.getValue();
                String logic = value.getLogic();
                for (UserQueryDTO.Condition condition : value.getConditions()) {
                    String operator = condition.getOperator();
                    String ibaValue = condition.getValue();
                    if ("state".equals(key)) {
                        if (lifeCycleStateMap.containsKey(ibaValue)) {
                            condition.setValue(lifeCycleStateMap.get(ibaValue));
                        } else {
                            throw RTErrorCodeEnum.DEV_CODE_EXIST.getException("输入的状态在系统中不存在!");
                        }
                    } else if ("modifier".equals(key) || "creator".equals(key)) {
                        if (!"equals".equals(operator) && !"notEquals".equals(operator)) {
                            continue;
                        }
                        List<UserDO> userDOS = typlmUserService.fuzzyQueryUserForEnabled(ibaValue);
                        if (CollUtil.isNotEmpty(userDOS)) {
                            condition.setValue(userDOS.get(0).getOid().toString());
                        } else {
                            throw RTErrorCodeEnum.DEV_CODE_EXIST.getException("输入的创建人/修改人不存在!");
                        }
                    } else if ("createstamp".equals(key) || "modifystamp".equals(key)) {
                        continue;
                    }
                    SearchAttributeVO searchAttributeVO = attributeMap.get(key);
                    if ("contains".equals(operator)) {
                        searchAttributeVO.setPropertyValue("*" + condition.getValue() + "*");
                        searchAttributeVO.setSymbol("=");
                    } else if ("notContains".equals(operator)) {
                        searchAttributeVO.setPropertyValue("*" + condition.getValue() + "*");
                        searchAttributeVO.setSymbol("!=");
                    } else if ("equals".equals(operator)) {
                        searchAttributeVO.setPropertyValue(condition.getValue());
                        searchAttributeVO.setSymbol("=");
                    } else if ("notEquals".equals(operator)) {
                        searchAttributeVO.setPropertyValue(condition.getValue());
                        searchAttributeVO.setSymbol("!=");
                    } else if ("startsWith".equals(operator)) {
                        searchAttributeVO.setPropertyValue(condition.getValue() + "*");
                        searchAttributeVO.setSymbol("=");
                    } else if ("notStartsWith".equals(operator)) {
                        searchAttributeVO.setPropertyValue(condition.getValue() + "*");
                        searchAttributeVO.setSymbol("!=");
                    } else if ("endsWith".equals(operator)) {
                        searchAttributeVO.setPropertyValue("*" + condition.getValue());
                        searchAttributeVO.setSymbol("=");
                    } else if ("isEmpty".equals(operator)) {
                        searchAttributeVO.setPropertyValue("* *");
                        searchAttributeVO.setSymbol("=");
                    } else if ("isNotEmpty".equals(operator)) {
                        searchAttributeVO.setPropertyValue(" ");
                        searchAttributeVO.setSymbol("!=");
                    }
                    SearchAttributeDTO searchAttributeDTO = new SearchAttributeDTO();
                    try {
                        BeanUtils.copyProperties(searchAttributeDTO, searchAttributeVO);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    conditions.add(searchAttributeDTO);
                }
                SearchAttributeGroupDTO searchAttributeGroupDTO = new SearchAttributeGroupDTO();
                searchAttributeGroupDTO.setConditionJoint(logic);
                searchAttributeGroupDTO.setConditions(conditions);
                conditionGroups.add(searchAttributeGroupDTO);
            }
        } else {
            List<SearchAttributeDTO> conditions = new ArrayList<>();
            SearchAttributeVO searchAttributeVO = attributeMap.get("number");
            searchAttributeVO.setPropertyValue(" ");
            searchAttributeVO.setSymbol("!=");
            SearchAttributeDTO searchAttributeDTO = new SearchAttributeDTO();
            try {
                BeanUtils.copyProperties(searchAttributeDTO, searchAttributeVO);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            searchAttributeDTO.setTypeList(new ArrayList<>());
            searchAttributeDTO.setAttrDefOid(null);
            searchAttributeDTO.setAttrDefOtype(null);
            conditions.add(searchAttributeDTO);
            SearchAttributeGroupDTO searchAttributeGroupDTO = new SearchAttributeGroupDTO();
            searchAttributeGroupDTO.setConditionJoint("and");
            searchAttributeGroupDTO.setConditions(conditions);
            conditionGroups.add(searchAttributeGroupDTO);
        }

        searchConditionDTO.setConditionGroups(conditionGroups);
        searchConditionDTO.setPageNum(userQueryDTO.getPageNum());
        searchConditionDTO.setPageSize(userQueryDTO.getPageSize());
        searchConditionDTO.setNeedIBA(needIBA);
        searchConditionDTO.setNeedThumbnailFile(needThumbnailFile);
        searchConditionDTO.setNeedCount(true);
        searchConditionDTO.setNoExtProperty(false);
        searchConditionDTO.setShowAllViewVersion(false);
        searchConditionDTO.setLimitContext(false);
        searchConditionDTO.setNeedEmptyCondition(false);
        searchConditionDTO.setNeedSort(false);
        searchConditionDTO.setNeedLatest(false);
        searchConditionDTO.setUsedReport(false);
        searchConditionDTO.setExportReport(false);
        return typlmCommonSearchService.queryByConditionForPage(searchConditionDTO);
    }

    private static @NotNull List<String> getIbaList() {
        List<String> ibaList = new ArrayList<>();
        ibaList.add("编号");
        ibaList.add("名称");
        ibaList.add("拼接描述");
        ibaList.add("历史描述");
        ibaList.add("3D源图号");
        ibaList.add("输出要求");
        ibaList.add("备注");
        ibaList.add("变化类型");
        ibaList.add("变化点");
        ibaList.add("创建时间");
        ibaList.add("创建者");
        ibaList.add("修改时间");
        ibaList.add("修改者");
        ibaList.add("设计变更通知编号");
        ibaList.add("升版备注");
        ibaList.add("描述修改提出者");
        ibaList.add("开发令");
        ibaList.add("机型");
        ibaList.add("零部件代码");
        ibaList.add("状态");
        return ibaList;
    }


    @Override
    public List<SearchAttributeVO> getIbaByTypeName(String type) {
        TypeDO typeDO = typlmTypeService.getLastTypeByLogicalidentifier(type.split("\\|")[1]);
        List<SearchTypeVO> list = new ArrayList<>();
        SearchTypeVO searchTypeVO = new SearchTypeVO();
        searchTypeVO.setTypeOid(typeDO.getOid());
        searchTypeVO.setTypeInthid(type);
        list.add(searchTypeVO);
        return typlmCommonSearchService.getSearchAttribute(list);
    }


    @Override
    public void autoCollectPart(BigInteger workflowContainerId) {
        // 获取工作流容器详情
        WorkFlowContainerView containerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(
                workflowContainerId);
        if (containerView instanceof WorkFlowObjectPackage) {
            log.info("当前流程属于普通流程");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) containerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isEmpty(flowObjectList)) {
                return;
            }
            flowObjectList = flowObjectList.stream()
                    .filter(m -> m.getRefObjectOtype().equalsIgnoreCase(TableTypeConstrant.TY_PART_OTYPE))
                    .collect(Collectors.toList());
            if (CollUtil.isEmpty(flowObjectList)) {
                return;
            }
            List<BaseObject> result = new ArrayList<>();
            BigInteger containerId = workFlowObjectPackage.getOid();
            BigInteger workFlowId = workFlowObjectPackage.getWorkFlowId();
            List<String> partNumberList = new ArrayList<>();
            List<String> lifeCycleStageKeyList = new ArrayList<>();
            for (FlowObject flowObject : flowObjectList) {
                BigInteger refObjectOid = flowObject.getRefObjectOid();
                String refObjectOType = flowObject.getRefObjectOtype();
                result.add(new BaseObject(refObjectOid, refObjectOType));
                partNumberList.add(flowObject.getRefObjectNumber());
                lifeCycleStageKeyList.add(flowObject.getLifeCycleStageKey());
            }
            List<String> types = Collections.singletonList("MaterialCode");
            List<PartDO> partDOS = rtPartMapper.queryPartByNumber(partNumberList, "Design", types,
                                                                  lifeCycleStageKeyList);
            List<String> list = new ArrayList<>();
            for (PartDO partDO : partDOS) {
                String lockstateinfo = partDO.getLockstateinfo();
                if ("c/i".equals(lockstateinfo)) {
                    result.add(new BaseObject(partDO.getOid(), partDO.getOtype()));
                } else {
                    list.add(partDO.getObjnumber());
                }
            }
            if (CollUtil.isNotEmpty(list)) {
                throw RTErrorCodeEnum.DEV_CODE_EXIST.getException("物料:" + String.join(",", list) + "未检入！");
            }
            if (CollUtil.isEmpty(result)) {
                return;
            }
            // 同步处理
            addIntoWorkFlow(workFlowId, containerId, result, flowObjectList);
        }
    }


    private void addIntoWorkFlow(BigInteger workFlowId, BigInteger containerId, List<BaseObject> objList,
                                 List<FlowObject> flowObjectList) {
        FlowObjectStructuredParamVO flowObjectStructuredParamVO = new FlowObjectStructuredParamVO();
        flowObjectStructuredParamVO.setObjList(objList);
        flowObjectStructuredParamVO.setWorkFlowId(workFlowId);
        flowObjectStructuredParamVO.setWorkFlowContainerId(containerId);
        flowObjectStructuredParamVO.setRootObjList(flowObjectList);
        flowObjectStructuredParamVO.setOirAllObjList(flowObjectList);
        flowObjectStructuredParamVO.setSaveDataBase(true);
        log.info("flowObjectStructuredParamVO>>>>>>>>>>>>>>>>>>>>>>>{}",
                 JSON.toJSONString(flowObjectStructuredParamVO));
        this.typlmWorkFlowObjectPackageService.addCheckWorkFlowStartNoThrowCommon(flowObjectStructuredParamVO);
    }

    @Override
    public Set<String> queryPartAndIbaByType(UserQueryDTO queryPartIFDTO) {
        Set<String> set = new HashSet<>();
        PageInfo<ResultEntityVO> resultEntityVOPageInfo = queryPartData(queryPartIFDTO, Boolean.FALSE, Boolean.TRUE);
        List<ResultEntityVO> list = resultEntityVOPageInfo.getList();
        for (ResultEntityVO resultEntityVO : list) {
            List<AttributeVO> ibaAttrs = resultEntityVO.getIbaAttrs();
            Map<String, List<String>> ibaAttribute = ibaAttrs.stream()
                    .collect(Collectors.groupingBy(
                            AttributeVO::getAttributeEnName,
                            Collectors.mapping(AttributeVO::getAttributeValue, Collectors.toList())
                    ));
            String name = attributePropagationService.generateProductSpectrumName(ibaAttribute);
            set.add(name);
        }
        return set;
    }


    @Override
    public List<ResultEntityVO> getVersionHistory(IdentifierEntity identifierEntity) {
        // 参数校验
        TyplmEntityBaseUtil.checkParamNotNull(identifierEntity, "identifierEntity");

        // 获取部件信息
        TyPartAllVO partAllVO = typlmPartService.queryPartAllVO(
                identifierEntity.getOid(),
                identifierEntity.getOtype()
        );

        if (partAllVO == null || !isPatternCodeType(partAllVO)) {
            return Collections.emptyList();
        }

        String partNumber = partAllVO.getObjectNumber();

        List<PartDO> partDOS = rtPartMapper.queryAllVersionPartByVersionAndView(
                partNumber.substring(0, 11) + "*", "Design", null, "PatternCode");

        List<IdentifierEntity> identifierEntityList = new ArrayList<>();
        for(PartDO partDO : partDOS){
            identifierEntityList.add(new IdentifierEntity(partDO.getOid(), partDO.getOtype()));
        }
        SearchConditionDTO searchConditionDTO = new SearchConditionDTO();
        searchConditionDTO.setIdentifiers(identifierEntityList);
        searchConditionDTO.setNeedIBA(true);
        TyQueryByIdentifierEvent tyQueryByIdentifierEvent = new TyQueryByIdentifierEvent(this, searchConditionDTO);
        applicationEventPublisher.publishEvent(tyQueryByIdentifierEvent);
        List<ResultEntityVO> resultEntityVOS = tyQueryByIdentifierEvent.getResultEntityVOS();
        resultEntityVOS.sort((o1, o2) -> {
            // 首先按objectNumber逆序排序
            int objectNumberCompare = o2.getObjectNumber().compareTo(o1.getObjectNumber());
            if (objectNumberCompare != 0) {
                return objectNumberCompare;
            }

            // 如果objectNumber相同，按majorVersion字母逆序排序
            return o2.getMajorVersion().compareTo(o1.getMajorVersion());
        });
        return resultEntityVOS;
    }

    @Override
    public void exportPartDataFile(UserQueryDTO queryPartIFDTO, HttpServletResponse response) {
        ExcelWriter excelWriter = null;
        try {
            // 设置查询参数
            queryPartIFDTO.setPageNum(1);
            queryPartIFDTO.setPageSize(9999999);

            // 获取数据
            List<ResultEntityVO> dataList = queryPartData(queryPartIFDTO, Boolean.FALSE, Boolean.TRUE).getList();

            // 获取导出类型
            String typeInthid = queryPartIFDTO.getTypeInthid();

            // 设置响应头
            setupResponseHeader(response, getFileName(typeInthid));

            // 根据类型导出数据
            switch (typeInthid) {
                case "ty.inteplm.part.CTyPart|EBOM_NUM": // EBOM物料
                    exportWithMultipleSheets(dataList, response, ExportEBOMPartsDataVO.class, "EBOM", this::convertToEBomVo);
                    break;
                case "ty.inteplm.part.CTyPart|MaterialCode": // 物料码
                    exportWithMultipleSheets(dataList, response, ExportMaterialCodePartsDataVO.class, "物料码", this::convertToMaterialVo);
                    break;
                case "ty.inteplm.part.CTyPart|PatternCode": // 图样代号
                    exportWithMultipleSheets(dataList, response, ExportPatternCodePartsDataVO.class, "图样代号", this::convertToPatternVo);
                    break;
                case "ty.inteplm.part.CTyPart|Standard": // 标准件
                    exportWithMultipleSheets(dataList, response, ExportStandardPartsDataVO.class, "标准件", this::convertToStandardVo);
                    break;
                default:
                    throw RTErrorCodeEnum.DRAWING_CODE_NAME_ERROR.getException("不支持的导出类型: " + typeInthid);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw RTErrorCodeEnum.DRAWING_CODE_NAME_ERROR.getException(e.getMessage());
        } finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    /**
     * 通用多Sheet导出方法
     */
    private <T> void exportWithMultipleSheets(List<ResultEntityVO> dataList,
                                              HttpServletResponse response,
                                              Class<T> clazz,
                                              String sheetBaseName,
                                              Function<ResultEntityVO, T> converter) throws IOException {

        // 转换数据
        List<T> exportData = dataList.stream()
                .map(converter)
                .collect(Collectors.toList());

        // 分割数据到多个Sheet
        List<List<T>> sheetDataList = splitList(exportData);

        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcel.write(response.getOutputStream(), clazz).build();

            // 写入多个Sheet
            for (int i = 0; i < sheetDataList.size(); i++) {
                WriteSheet writeSheet = EasyExcel.writerSheet(i, getSheetName(sheetBaseName, i))
                        .build();
                excelWriter.write(sheetDataList.get(i), writeSheet);
            }

        } finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    /**
     * 数据转换方法
     */
    private ExportEBOMPartsDataVO convertToEBomVo(ResultEntityVO source) {
        ExportEBOMPartsDataVO vo = new ExportEBOMPartsDataVO();
        Map<String, String> ibaMap = convertIbaAttrsToMap(source);
        vo.setCode(source.getObjectNumber());
        vo.setSplicingDesc(ibaMap.get("Description"));//拼接描述
        vo.setRemark(ibaMap.get("REMARK"));//备注
        vo.setCreator(source.getCreatorName());
        vo.setCreateTime(sdf.format(source.getCreatestamp()));
        vo.setModifier(source.getUpdatorName());
        vo.setModifyTime(sdf.format(source.getModifystamp()));
        vo.setDescModifierProposer(ibaMap.get("Proposer"));
        vo.setDescModifyOpinion(ibaMap.get("RevisionOpinions"));
        vo.setLifeCycle(source.getLifecyclestagekeyName());
        vo.setAuditor(ibaMap.get("Reviewer"));
        vo.setMainPromoteModel(ibaMap.get("MainRecommendedModels"));
        vo.setMainPromoteStatus(ibaMap.get("MainPushStatus"));
        vo.setHistoryDesc(ibaMap.get("historyDescription"));
        vo.setDevelopmentOrder(ibaMap.get("devCode"));
        vo.setModelNo(ibaMap.get("MachineModel"));
        vo.setProductSpectrumName(ibaMap.get("ProductSpectrumName"));
        vo.setProductSubCategory(ibaMap.get("ProductSeries"));
        return vo;
    }

    private ExportMaterialCodePartsDataVO convertToMaterialVo(ResultEntityVO source) {
        ExportMaterialCodePartsDataVO vo = new ExportMaterialCodePartsDataVO();
        Map<String, String> ibaMap = convertIbaAttrsToMap(source);
        vo.setCode(source.getObjectNumber());                         // 编码
        vo.setCodeName(source.getName());                                   // 编码名称
        vo.setSplicingDesc(ibaMap.get("Description"));                               // 拼接描述
        vo.setOutputReq(ibaMap.get("OutputRequirements"));                                  // 输出要求
        vo.setHistoryDesc(ibaMap.get("historyDescription"));                                // 历史描述
        vo.setRemark(ibaMap.get("REMARK"));                                        // 备注
        vo.setApplicant(ibaMap.get("applicant"));                                    // 申请人
        vo.setCreator(source.getCreatorName());                                     // 创建人
        vo.setCreateTime(sdf.format(source.getCreatestamp()));                                 // 创建时间
        vo.setUnit(ibaMap.get("UnitMeasurement"));                                      // 计量单位
        //TODO
        vo.setManufacturingAttr(ibaMap.get(""));                          // 制造属性
        vo.setDrawingNo(ibaMap.get("PatternCode"));                                 // 图样代号
        vo.setLifeCycle(source.getLifecyclestagekeyName());                                 // 生命周期
        vo.setDisableTime(sdf.format(source.getModifystamp()));                               // 停用时间
        vo.setModifier(source.getUpdatorName());                                    // 修改人
        vo.setModifyTime(sdf.format(source.getModifystamp()));                                // 修改时间
        vo.setDescModifierProposer(ibaMap.get("proposer"));                 // 描述修改提出人
        vo.setDescModifyOpinion(ibaMap.get("RevisionOpinions"));                      // 描述修改意见
        vo.setAuditor(ibaMap.get("Reviewer"));                                     // 审核人
        vo.setDevelopmentOrder(ibaMap.get("devCode"));                            // 开发令
        vo.setModelNo(ibaMap.get("productType"));                                     // 机型号
        vo.setPartCode(ibaMap.get("ComponentCode"));                                  // 零部件码
        vo.setThreeDSourceDrawingNo(ibaMap.get("3DDrawingNumber"));                     // 3D源图号
        return vo;
    }

    private ExportPatternCodePartsDataVO convertToPatternVo(ResultEntityVO source) {
        ExportPatternCodePartsDataVO vo = new ExportPatternCodePartsDataVO();
        Map<String, String> ibaMap = convertIbaAttrsToMap(source);
        vo.setCode(source.getObjectNumber());                    // 编码
        vo.setCodeName(source.getName());                              // 编码名称
        vo.setSplicingDesc(ibaMap.get("description"));                          // 拼接描述
        vo.setHistoryDesc(ibaMap.get("historyDescription"));                           // 历史描述
        vo.setThreeDSourceDrawingNo(ibaMap.get("3DDrawingNumber"));                // 3D源图号
        vo.setOutputReq(ibaMap.get("OutputRequirements"));                             // 输出要求
        vo.setRemark(ibaMap.get("remark"));                                   // 备注
        vo.setChangeType(ibaMap.get("VariationType"));                            // 变化类型
        vo.setChangePoint(ibaMap.get("ChangePoint"));                             // 变化点
        vo.setCreator(source.getCreatorName());                                // 创建人
        vo.setCreateTime(sdf.format(source.getCreatestamp()));                            // 创建时间
        vo.setModifier(source.getUpdatorName());                               // 修改人
        vo.setModifyTime(sdf.format(source.getModifystamp()));                            // 修改时间
        vo.setDesignChangeNoticeNo(ibaMap.get("NoticeChangeNumber"));          // 设计变更通知编号
        vo.setVersionUpgradeRemark(ibaMap.get("UpgradeRemarks"));                 // 升版备注
        vo.setDescModifierProposer(ibaMap.get("proposer"));            // 描述修改提出者
        vo.setDisableTime(sdf.format(source.getModifystamp()));                           // 停用时间
        vo.setLifeCycle(source.getLifecyclestagekeyName());                            // 生命周期
        vo.setDevelopmentOrder(ibaMap.get("devCode"));                       // 开发令
        vo.setModelNo(ibaMap.get("productType"));                                // 机型号
        vo.setPartCode(ibaMap.get("ComponentCode"));                             // 零部件码
        return vo;
    }

    private ExportStandardPartsDataVO convertToStandardVo(ResultEntityVO source) {
        ExportStandardPartsDataVO vo = new ExportStandardPartsDataVO();
        Map<String, String> ibaMap = convertIbaAttrsToMap(source);
        vo.setCode(source.getObjectNumber());                  // 编码
        vo.setCodeName(source.getName());                           // 编码名称
        vo.setSplicingDesc(ibaMap.get("Description"));                       // 拼接描述
        //TODO
        vo.setManufacturingAttr("");                   // 制造属性
        vo.setRemark(ibaMap.get("REMARK"));                                // 备注
        vo.setCreator(source.getCreatorName());                             // 创建人
        vo.setCreateTime(sdf.format(source.getCreatestamp()));                         // 创建时间
        vo.setModifier(source.getUpdatorName());                            // 修改人
        vo.setModifyTime(sdf.format(source.getModifystamp()));                         // 修改时间
        vo.setLifeCycle(source.getLifecyclestagekeyName());                         // 生命周期
        vo.setAuditor(ibaMap.get("applicant"));                             // 审核人
        vo.setUnit(ibaMap.get("UnitMeasurement"));                              // 计量单位
        vo.setPartCode(ibaMap.get("ComponentCode"));                          // 零部件码
        vo.setHazardousSubstance(ibaMap.get("hazardousSubstance"));                 // 有害物质
        vo.setSpecification(ibaMap.get("specification"));                         // 规格
        vo.setPitch(ibaMap.get("screwPitch"));                                // 螺距
        vo.setPerformance(ibaMap.get("performance"));                           // 性能
        vo.setSurfaceTreatment(ibaMap.get("surfaceTreatment"));                   // 表面处理
        vo.setSpecialReq(ibaMap.get("specialRequirement"));                        // 特殊要求
        vo.setDescModifierProposer(ibaMap.get("Proposer"));         // 描述修改提出者
        vo.setDescModifyOpinion(ibaMap.get("RevisionOpinions"));              // 描述修改意见
        vo.setDisableTime(sdf.format(source.getModifystamp()));                       // 停用时间
        return vo;
    }

    private Map<String, String> convertIbaAttrsToMap(ResultEntityVO source) {
        List<AttributeVO> ibaAttrs = source.getIbaAttrs();
        Map<String, String> ibaAttrMapForSearch = source.getIbaAttrMapForSearch();

        if (ibaAttrs == null || ibaAttrs.isEmpty()) {
            return Collections.emptyMap();
        }

        Map<String, String> result = new HashMap<>();
        boolean hasSearchMap = CollUtil.isNotEmpty(ibaAttrMapForSearch);

        for (AttributeVO attr : ibaAttrs) {
            if (attr != null && attr.getAttributeEnName() != null) {
                String value = hasSearchMap ?
                        ibaAttrMapForSearch.getOrDefault(attr.getAttributeOid(),
                                                         attr.getAttributeValue() != null ? attr.getAttributeValue() : "") :
                        (attr.getAttributeValue() != null ? attr.getAttributeValue() : "");

                result.put(attr.getAttributeEnName(), value);
            }
        }
        return result;
    }

    /**
     * 设置响应头
     */
    private void setupResponseHeader(HttpServletResponse response, String baseFileName)
            throws UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name()); // 这里用name()方法获取字符串
        String fileName = baseFileName + "_" + System.currentTimeMillis() + ".xlsx";
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
        response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName);
    }

    /**
     * 根据类型获取文件名
     */
    private String getFileName(String typeInthid) {
        switch (typeInthid) {
            case "ty.inteplm.part.CTyPart|EBOM_NUM": return "EBOM物料";
            case "ty.inteplm.part.CTyPart|MaterialCode": return "物料码";
            case "ty.inteplm.part.CTyPart|PatternCode": return "图样代号";
            case "ty.inteplm.part.CTyPart|Standard": return "标准件";
            default: return "导出数据";
        }
    }

    private static final int MAX_SHEET_SIZE = 50000; // 每个Sheet最大数据量

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 将大数据列表分割成多个小列表
     */
    public static <T> List<List<T>> splitList(List<T> sourceList) {
        List<List<T>> result = new ArrayList<>();
        if (sourceList == null || sourceList.isEmpty()) {
            return result;
        }

        int totalSize = sourceList.size();
        int sheetCount = (totalSize + MAX_SHEET_SIZE - 1) / MAX_SHEET_SIZE;

        for (int i = 0; i < sheetCount; i++) {
            int fromIndex = i * MAX_SHEET_SIZE;
            int toIndex = Math.min((i + 1) * MAX_SHEET_SIZE, totalSize);
            result.add(sourceList.subList(fromIndex, toIndex));
        }

        return result;
    }

    /**
     * 获取Sheet名称
     */
    public static String getSheetName(String baseName, int index) {
        return baseName + (index + 1);
    }

    /**
     * 检查部件是否为PatternCode类型
     */
    private boolean isPatternCodeType(TyPartAllVO partAllVO) {
        BigInteger typeOid = partAllVO.getTypeoid();
        TypeDO typeDO = typlmTypeService.queryTypeByOID(typeOid);
        return typeDO != null && "PatternCode".equals(typeDO.getName());
    }


}
